@forsion/unit 2.12.2 → 2.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -0
- package/backendWorker.mjs +6 -2
- package/main.mjs +991 -497
- package/package.json +1 -1
- package/release.json +5 -5
- package/web/assets/ArtificialView-XwHMLUFb.js +1 -0
- package/web/assets/{AutomationBuilder-sxWdUa0L.js → AutomationBuilder-hqs0QhMt.js} +1 -1
- package/web/assets/CalendarConfigView-DKib8Oed.js +1 -0
- package/web/assets/CalendarView-DJ5iOzvu.js +1 -0
- package/web/assets/CapabilityMenu-SwVlZ06x.js +1 -0
- package/web/assets/{CheckboxInput-BsaoUHZ0.js → CheckboxInput-BC-5a_C9.js} +1 -1
- package/web/assets/Chrome-HdfyYV3i.js +1 -0
- package/web/assets/{CodeView-j065KtVh.js → CodeView-CFL6yQ-6.js} +3 -3
- package/web/assets/DashboardGridView-B9DCWYVb.js +17 -0
- package/web/assets/{EventCard-BmDQkEj9.js → EventCard-B_ndpqH_.js} +1 -1
- package/web/assets/ExcalidrawCanvas-BQ4KKLJP.js +1 -0
- package/web/assets/{FloatingToc-CENybkAA.js → FloatingToc-Ce9GamvH.js} +1 -1
- package/web/assets/HomepageView-RCOfcVbE.js +1 -0
- package/web/assets/ImageStudioPanels-lkS_y2uM.js +3 -0
- package/web/assets/ImageStudioView-UPv52acl.js +1 -0
- package/web/assets/InlineFiles-CQbQumkf.js +1 -0
- package/web/assets/MarkdownBlock--__nPQGh.css +1 -0
- package/web/assets/MarkdownBlock-CkqiwPXa.js +58 -0
- package/web/assets/ModelPill-CY-rU1RU.js +2 -0
- package/web/assets/MuseLibraryView-CtTHlVnT.js +2 -0
- package/web/assets/{MuseView-d-iBk3sc.js → MuseView-CC2A7MBs.js} +2 -2
- package/web/assets/{PageHistoryPanel-CR-k1AM7.js → PageHistoryPanel-KhKT1DLy.js} +2 -2
- package/web/assets/PdfAnnotator-C_kglLCA.css +1 -0
- package/web/assets/PdfAnnotator-DUyrgY-t.js +505 -0
- package/web/assets/{ProductView-u2aezVsl.js → ProductView-CgsIYZqD.js} +1 -1
- package/web/assets/RightPanel-BHDgqTFs.js +4 -0
- package/web/assets/RunLocationPicker-BE5mxnab.css +1 -0
- package/web/assets/RunLocationPicker-DBnXYV5B.js +38 -0
- package/web/assets/{SidebarRow-BuSkKH5q.js → SidebarRow-BAJxbMcx.js} +1 -1
- package/web/assets/{SketchCard-D87GADyG.js → SketchCard-BGYz-bXP.js} +5 -5
- package/web/assets/{StudioGuestSurface-BijU_EEb.js → StudioGuestSurface-lt6znmkl.js} +1 -1
- package/web/assets/{TodoListView-DPPVpPUn.js → TodoListView-DPKhee6i.js} +1 -1
- package/web/assets/{Tooltip-DY4ISA-e.js → Tooltip-ZxrDqN4p.js} +1 -1
- package/web/assets/UnifiedPage-BX6ZQL0h.js +68 -0
- package/web/assets/UnifiedPage-CWXc_mo1.css +1 -0
- package/web/assets/{amadeus-manual.en-DWaN2fPs.js → amadeus-manual.en-DzRWr4BL.js} +18 -18
- package/web/assets/{amadeus-manual.zh--7D5TS8X.js → amadeus-manual.zh-DW32DkL7.js} +18 -18
- package/web/assets/{appStore-Dg9WALEA.js → appStore-DWP8UET9.js} +208 -122
- package/web/assets/appStore-wtOILggO.css +1 -0
- package/web/assets/{arrow-up-right-CpQs92mu.js → arrow-up-right-DrCXuWS7.js} +1 -1
- package/web/assets/{astryxBridge-BZhaZPs4.js → astryxBridge-D-m4_kYt.js} +3 -3
- package/web/assets/automationListSource-C8BNy6RY.js +1 -0
- package/web/assets/book-open-OLNm7OaB.js +1 -0
- package/web/assets/{calendarNavStore-C7fGRpoH.js → calendarNavStore-Cylfvv3s.js} +1 -1
- package/web/assets/{canvasPrefs-BeG4oEgP.js → canvasPrefs-8taQ42Cz.js} +1 -1
- package/web/assets/chatBoxSurface-CIlzs45H.js +1 -0
- package/web/assets/{circle-question-mark-WL3vbp-Z.js → circle-question-mark-XbAFplz1.js} +1 -1
- package/web/assets/{circle-x-D7s-M5sB.js → circle-x-fcReAZaE.js} +1 -1
- package/web/assets/{client-BSKpsyAw.js → client-0MPbodA6.js} +1 -1
- package/web/assets/{code-xml-BALV9u_c.js → code-xml-Cuna8Kh4.js} +1 -1
- package/web/assets/{codeStudioStore-C2mWfm32.js → codeStudioStore-BBU62GTy.js} +1 -1
- package/web/assets/codingNavigation-CZB4v1ZW.css +1 -0
- package/web/assets/codingNavigation-DDlPpPk5.js +47 -0
- package/web/assets/{create-4xUyKtAF.js → create-BGtEfCcg.js} +4 -4
- package/web/assets/dashboardSurface-BYM3C7WG.js +1 -0
- package/web/assets/{deskCapture-Df701U8L.js → deskCapture-BiUCmqfc.js} +1 -1
- package/web/assets/{diff2html-BV-zCH4d.js → diff2html-BNp2FTbk.js} +1 -1
- package/web/assets/{docx-preview-DW4IyU_Q.js → docx-preview-CFznGVOU.js} +1 -1
- package/web/assets/{emoji-DGaxpCIu.js → emoji-6zl4yfOS.js} +1 -1
- package/web/assets/floatingTocSurface-DreXPCa6.js +1 -0
- package/web/assets/{foldActions-B7KByFdN.js → foldActions-05QcQziQ.js} +1 -1
- package/web/assets/folder-BpsfOHD4.js +1 -0
- package/web/assets/{folder-plus-D1TDb7k9.js → folder-plus-BeQHr4AZ.js} +1 -1
- package/web/assets/gestures-DQBCcK4y.js +1 -0
- package/web/assets/{hand-Crrw-nSn.js → hand-Bko7ms15.js} +1 -1
- package/web/assets/{hard-drive-BbyVSbfP.js → hard-drive-BpuI5ebj.js} +1 -1
- package/web/assets/i18n-ecQQxiMQ.css +1 -0
- package/web/assets/i18n.generated-BuLjnmY8.js +15 -0
- package/web/assets/imageStudio--KF9gwHA.css +1 -0
- package/web/assets/imageStudio-BLVNKmEG.js +2 -0
- package/web/assets/{index-DKhyDkGB.js → index-BF10xp_K.js} +1 -1
- package/web/assets/{index-C7U6T-k8.js → index-BHm6K743.js} +1 -1
- package/web/assets/{index-CF4RV4mh.js → index-BM2o7PeV.js} +90 -90
- package/web/assets/{index-Brik2pf9.js → index-BgnNNv3e.js} +1 -1
- package/web/assets/{index--drOLtq7.js → index-C0Gy2NQ6.js} +1 -1
- package/web/assets/{index-CflzrdSt.js → index-C1doZp5H.js} +1 -1
- package/web/assets/{index-SZ5waGAq.js → index-C4L6vjd_.js} +1 -1
- package/web/assets/{index-Cmr7gVZQ.js → index-CD3yIkOA.js} +1 -1
- package/web/assets/{index-BYsdKR_1.js → index-CJeUgjPU.js} +1 -1
- package/web/assets/{index-CzM-C2Sd.js → index-CLHoq1w-.js} +1 -1
- package/web/assets/{index-tAXBa_fN.js → index-CUZI62qU.js} +1 -1
- package/web/assets/{index-C6GJulug.js → index-Cff42k7q.js} +1 -1
- package/web/assets/index-Ck_O3Jdd.js +1 -0
- package/web/assets/index-CuiYK18N.js +1 -0
- package/web/assets/{index-BRW82CsP.js → index-CwcOeZdT.js} +1 -1
- package/web/assets/{index-DUWR2nZi.js → index-D6AycQIz.js} +1 -1
- package/web/assets/{index-BCZZVJ_w.js → index-D7gVhvNY.js} +1 -1
- package/web/assets/{index-DjzSBM0U.js → index-D9UZQy42.js} +1 -1
- package/web/assets/{index-KL5Rj9kP.js → index-DuBQ0j2g.js} +1 -1
- package/web/assets/{index-Dg9oixs4.js → index-OD1gSX3h.js} +1 -1
- package/web/assets/{index-gPSbFSUn.js → index-Uo5tswys.js} +1 -1
- package/web/assets/{index-D1f_JwPH.js → index-o8cj0pRH.js} +1 -1
- package/web/assets/{index-OHi69jDq.js → index-rHjhbwvm.js} +1 -1
- package/web/assets/{index-CqyM6tQ0.js → index-rggq2czF.js} +1 -1
- package/web/assets/{index-Czu_bbDM.js → index-sCXThwqZ.js} +1 -1
- package/web/assets/{invitePage-lLQ-e0pj.js → invitePage-b0HGvMj6.js} +1 -1
- package/web/assets/{ipc-DQOD2UKk.js → ipc-CxAyeo8q.js} +1 -1
- package/web/assets/{jszip.min-DZxV9uZ_.js → jszip.min-B94KpE21.js} +1 -1
- package/web/assets/launchpad-C2c1MSVX.css +1 -0
- package/web/assets/{layout-grid-B_pjJwz4.js → layout-grid-BBVuEdWG.js} +1 -1
- package/web/assets/{linkFollow-C0_3k_PC.js → linkFollow-B7ivDZMM.js} +4 -4
- package/web/assets/{list-tree-DkAJYEXd.js → list-tree-4-0QDbLu.js} +1 -1
- package/web/assets/{listFold-BsOVn9UZ.js → listFold-DLuxXiIj.js} +1 -1
- package/web/assets/{lock-BnGHxjeE.js → lock-CnbZm4vo.js} +1 -1
- package/web/assets/{log-out-DBuMeqik.js → log-out-BEynWaHa.js} +1 -1
- package/web/assets/{main-NgUPPqDn.css → main-BiS_5wrB.css} +1 -1
- package/web/assets/main-sIq2N9Z5.js +20 -0
- package/web/assets/markdownEditorSurface-ZSJ3RHAv.js +3 -0
- package/web/assets/mdMarkStore-DQHDjG7s.js +2 -0
- package/web/assets/{mdMarks-Bq7Hl-4C.js → mdMarks-DbIcRa0O.js} +1 -1
- package/web/assets/{message-square-plus-BiAZAvcw.js → message-square-plus-CpiKDvle.js} +1 -1
- package/web/assets/{messages-BH5MfQdZ.js → messages-_jta1lSI.js} +1 -1
- package/web/assets/minus-C9ndHJ9O.js +1 -0
- package/web/assets/mobileEntry-CPmU_c4m.js +13 -0
- package/web/assets/nativeDownload-BYT082bY.js +1 -0
- package/web/assets/{pageChrome-xLNdFaSg.css → pageChrome-CovzZPdb.css} +1 -1
- package/web/assets/pageChrome-D3Niv1JM.js +1 -0
- package/web/assets/{pageTree-CZH2J6cc.js → pageTree-CgfvpzIj.js} +2 -2
- package/web/assets/{pen-tool-lkmBqliH.js → pen-tool-BXEFnU2i.js} +1 -1
- package/web/assets/{pencil-Cvk91P_Z.js → pencil-cqvCkekG.js} +1 -1
- package/web/assets/pluginChat-BbBukMuN.js +2 -0
- package/web/assets/{redo-2-DSi54z4e.js → redo-2-BO7wCDwy.js} +1 -1
- package/web/assets/{rotate-ccw-CUlnplr0.js → rotate-ccw-BvipPIjC.js} +1 -1
- package/web/assets/{sharePage-MM6UpPJ9.js → sharePage-XbN50US7.js} +2 -2
- package/web/assets/{shareViewer-CDZ8lTdy.js → shareViewer-BaYogetW.js} +1 -1
- package/web/assets/{star-CwDiGyUW.js → star-BQWMXnn7.js} +1 -1
- package/web/assets/tableSurface-BXqqidd1.js +1 -0
- package/web/assets/{terminal-DIXogYJY.js → terminal-l9k6RDrH.js} +1 -1
- package/web/assets/{terminalView-B3aZSsrQ.js → terminalView-Cpnt5_0P.js} +1 -1
- package/web/assets/theme-C6D3tMGV.css +1 -0
- package/web/assets/type-CFoaj2eD.js +1 -0
- package/web/assets/{undo-2-tUKCv5Gs.js → undo-2-DusxpdLa.js} +1 -1
- package/web/assets/{unitAccount-D8lVwaaT.js → unitAccount-DwutFPPw.js} +1 -1
- package/web/assets/{unitBridge-D547ublk.js → unitBridge-CcgQpkqV.js} +1 -1
- package/web/assets/{unitCloudTransport-BVF6lVp4.js → unitCloudTransport-vA7cLDts.js} +1 -1
- package/web/assets/{unitOwnerAccess-BfnEjsZb.js → unitOwnerAccess-LBlJ1YfA.js} +1 -1
- package/web/assets/{unitShim-DxetRgmP.js → unitShim-B_M9IrbC.js} +3 -3
- package/web/assets/{upload-BbeAsMuD.js → upload-ZrOj6tXA.js} +1 -1
- package/web/assets/userSpaces-uJOnsedR.js +1 -0
- package/web/assets/viewportLock-D3SNkwS2.js +631 -0
- package/web/assets/viewportLock-IP1zaVkz.css +1 -0
- package/web/assets/{workflow-DuoVRSSX.js → workflow-DPoG4QE2.js} +1 -1
- package/web/assets/{zoom-in-hr5bRpDL.js → zoom-in-lbTgzdQP.js} +1 -1
- package/web/index.html +232 -13
- package/web/assets/ArtificialView-B4ESD4iK.js +0 -1
- package/web/assets/CalendarConfigView-cCfo_EvZ.js +0 -1
- package/web/assets/CalendarView-wgLapctk.js +0 -1
- package/web/assets/CapabilityMenu-BQBsM638.js +0 -1
- package/web/assets/ChatView-BIUk0OJd.css +0 -1
- package/web/assets/ChatView-C-jCJnyS.js +0 -47
- package/web/assets/Chrome-CwFiDmre.js +0 -1
- package/web/assets/DashboardGridView-DXqe0vPd.js +0 -17
- package/web/assets/ExcalidrawCanvas-C3egkikA.js +0 -1
- package/web/assets/HomepageView-CRdhjLXu.js +0 -1
- package/web/assets/ImageStudioPanels-Dke7xf8E.js +0 -3
- package/web/assets/ImageStudioView-g38V8gaj.js +0 -1
- package/web/assets/InlineFiles-C_hjvn3u.js +0 -1
- package/web/assets/MarkdownBlock-DIjYEhTK.js +0 -56
- package/web/assets/ModelPill-BPlgovPo.js +0 -1
- package/web/assets/MuseLibraryView-CenyTTim.js +0 -2
- package/web/assets/PdfAnnotator-CGzC_o1Q.css +0 -1
- package/web/assets/PdfAnnotator-D79ip27w.js +0 -560
- package/web/assets/RightPanel-C3OJTIqT.js +0 -4
- package/web/assets/RunLocationPicker-BNcZ7KKF.css +0 -1
- package/web/assets/RunLocationPicker-CTYXUH2z.js +0 -34
- package/web/assets/UnifiedPage-CKNtVD_n.js +0 -57
- package/web/assets/UnifiedPage-DX_sTpyZ.css +0 -1
- package/web/assets/appStore-Di8LXuJ9.css +0 -1
- package/web/assets/automationListSource-DP5xZBxo.js +0 -1
- package/web/assets/chatBoxSurface-zvcyfrxE.js +0 -1
- package/web/assets/dashboardSurface-CFTH5z4c.js +0 -1
- package/web/assets/ellipsis-r1EcXsFq.js +0 -1
- package/web/assets/floatingTocSurface-C6RJ6i41.js +0 -1
- package/web/assets/folder-DlxnPmWY.js +0 -1
- package/web/assets/frame-_xBVYe3P.js +0 -1
- package/web/assets/gestures-CkW1Kfs9.js +0 -1
- package/web/assets/i18n-D-eU58uw.css +0 -1
- package/web/assets/i18n.generated-Bbsz16cl.js +0 -15
- package/web/assets/imageStudio-BqbNOvpu.css +0 -1
- package/web/assets/imageStudio-C_Rs630L.js +0 -2
- package/web/assets/index-BCubCwdT.js +0 -1
- package/web/assets/index-DZfZTksa.js +0 -1
- package/web/assets/main-Dki8NlsT.js +0 -21
- package/web/assets/markdownEditorSurface-B4PeUzed.js +0 -3
- package/web/assets/mdMarkStore-CsKl7C8O.js +0 -2
- package/web/assets/minus-Cyv1YzOU.js +0 -1
- package/web/assets/mobileEntry-Bd_nKr0D.js +0 -13
- package/web/assets/nativeDownload-D-f1_L2S.js +0 -1
- package/web/assets/pageChrome-C9_azUYW.js +0 -1
- package/web/assets/panel-left-rOc8As0s.js +0 -1
- package/web/assets/pen-line-m6_HvWZ9.js +0 -1
- package/web/assets/sticky-note-BIuPUSOU.js +0 -1
- package/web/assets/tableSurface-Y_JBQsuz.js +0 -1
- package/web/assets/theme-DfEi_DND.css +0 -1
- package/web/assets/type-Cqoabh7H.js +0 -1
- package/web/assets/userSpaces-DyyAn7vj.js +0 -1
- package/web/assets/viewportLock-C4SX-9PO.js +0 -103
- package/web/assets/viewportLock-DYSe7Jsn.css +0 -1
- package/web/assets/waves-horizontal-B8ZpHQ5H.js +0 -1
package/README.md
CHANGED
|
@@ -59,6 +59,28 @@ node main.mjs access /absolute/path/my-unit/unit.json
|
|
|
59
59
|
|
|
60
60
|
The default listener is loopback-only. The owner key stays in private instance data; the browser consumes it from the URL fragment, removes it and retains it only for that tab session. Keep instance data outside the release directory so code updates preserve data. `init` refuses to overwrite existing configuration.
|
|
61
61
|
|
|
62
|
+
## npm 发布 / npm package
|
|
63
|
+
|
|
64
|
+
每个桌面正式版(`v*` 标签)推上来后,`check-unit.yml` 的 `publish-npm` 把同一提交构建出的 Unit 发到 npm:`@forsion/unit`,版本号等于桌面版本号。包内是框架本体与网页壳(`main.mjs`、`backendWorker.mjs`、`web/`、`release.json`),不含按平台构建的本地插件。只发标签那一个提交的构建:`main` 上的构建与它跟着的正式版同号,`unit/check-publishable.mjs` 会拒绝。
|
|
65
|
+
|
|
66
|
+
After each stable Desktop release (`v*` tag), the `publish-npm` job in `check-unit.yml` publishes the Unit built from that commit as `@forsion/unit`, versioned like Desktop. The package holds the framework and its Web UI (`main.mjs`, `backendWorker.mjs`, `web/`, `release.json`) without the platform-specific local plugins. Only the tagged commit is published: a build from `main` shares the version of the release it follows, so `unit/check-publishable.mjs` refuses it.
|
|
67
|
+
|
|
68
|
+
```sh
|
|
69
|
+
# Take the prebuilt Unit without a Genesis checkout; it has no dependencies to install.
|
|
70
|
+
npm pack @forsion/unit@latest && tar -xzf forsion-unit-*.tgz # → ./package/main.mjs
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
发布走 npm trusted publishing(OIDC),仓库里没有 npm 令牌。npm 规定包存在后才能登记,所以首个版本要人工发一次:从该标签的 `check-unit` 运行里下载产物 `forsion-unit-npm`,然后
|
|
74
|
+
|
|
75
|
+
Publishing uses npm trusted publishing (OIDC); the repository holds no npm token. npm only lets an existing package register a publisher, so the first version is published once by hand: download the `forsion-unit-npm` artifact from that tag's `check-unit` run, then
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
npm login
|
|
79
|
+
npm publish ./forsion-unit-<version>.tgz --access public
|
|
80
|
+
# --allow-publish is required; `npm trust` needs npm ≥ 11.15.
|
|
81
|
+
npx -y npm@11 trust github @forsion/unit --repo Changan-Su/Forsion --file check-unit.yml --allow-publish
|
|
82
|
+
```
|
|
83
|
+
|
|
62
84
|
## 插件与生命周期 / Plugins and lifecycle
|
|
63
85
|
|
|
64
86
|
```sh
|
|
@@ -66,6 +88,7 @@ node main.mjs status /absolute/path/my-unit/unit.json
|
|
|
66
88
|
node main.mjs disable /absolute/path/my-unit/unit.json calendar
|
|
67
89
|
node main.mjs enable /absolute/path/my-unit/unit.json calendar
|
|
68
90
|
node main.mjs restart /absolute/path/my-unit/unit.json tangu
|
|
91
|
+
node main.mjs update /absolute/path/my-unit/unit.json calendar /absolute/path/calendar-package
|
|
69
92
|
node main.mjs install /absolute/path/my-unit/unit.json /absolute/path/new-plugin-package
|
|
70
93
|
```
|
|
71
94
|
|
|
@@ -73,6 +96,10 @@ node main.mjs install /absolute/path/my-unit/unit.json /absolute/path/new-plugin
|
|
|
73
96
|
|
|
74
97
|
Installing a new package with the same ID updates it. Running plugins can be replaced live, with rollback on activation failure. Dependencies determine lifecycle order; a dependency cannot be disabled while its dependents are active. Stop Unit before adding a new plugin. `migrate <config> <plugin-id>` applies only to inactive plugins that provide migrations. The local owner control channel is separate from browser visitor access.
|
|
75
98
|
|
|
99
|
+
显式在线更新使用 `update <unit.json> <plugin-id> <package-path>`。ID 必须已安装且与新包 manifest 一致;Unit 未运行时命令直接失败,不修改配置或执行迁移。包路径相对当前工作目录解析,必须指向已解包的插件目录。更新复用安装器的包、依赖与路径检查,将包复制到实例下独立的版本目录,再通过本机控制通道切换并持久化;之后移动或删除源包不会影响已安装版本。Unit 的进程和端口保持不变,更新包及其活跃依赖方按依赖顺序重启;无关插件继续运行。新包激活失败时恢复旧版服务,配置保留旧路径。离线替换仍可使用 `install`,下次启动时加载。
|
|
100
|
+
|
|
101
|
+
Use `update <unit.json> <plugin-id> <package-path>` for an explicit live update. The ID must already be installed and match the new manifest. If Unit is offline, the command fails without changing configuration or running migrations. The package path resolves from the current working directory and must name an unpacked plugin directory. Updates reuse the installer's package, dependency and path checks, copy the package into a separate instance version directory, then activate and persist it through the local control channel. Moving or deleting the source package afterward does not affect the installed version. Unit keeps its process and port; the updated plugin and its active dependents restart in dependency order while unrelated plugins keep running. Failed activation restores the previous service and keeps its configured path. Use `install` for an offline replacement that loads at the next startup.
|
|
102
|
+
|
|
76
103
|
插件继续使用 Forsion 的 `main`、Space 配方和插件 API。可选 `frontend.features` 激活共享界面中的 Amadeus、Tangu、Calendar、Automation、Public 功能;新增界面实现仍需更新 Unit。可信插件可声明 `runtime` 提供设备能力,或声明 `backend` 提供 HTTP 服务。接口分别见 `runtimeTypes.ts` 和 `backendTypes.ts`;支持这些通用接口不代表预装任何商业实现。
|
|
77
104
|
|
|
78
105
|
Plugins use Forsion's existing `main`, Space recipes and plugin API. Optional `frontend.features` activates Amadeus, Tangu, Calendar, Automation or Public in the shared renderer; new UI implementations still require a Unit update. Trusted plugins can declare `runtime` for device capabilities or `backend` for HTTP services, as defined in `runtimeTypes.ts` and `backendTypes.ts`. Supporting these generic contracts does not bundle a commercial implementation.
|
|
@@ -94,8 +121,42 @@ cd desktop
|
|
|
94
121
|
npm run typecheck
|
|
95
122
|
npm run check:parity
|
|
96
123
|
npx vitest run electron/unit*.test.ts electron/backendRunner.test.ts electron/basicUnit.test.ts
|
|
124
|
+
# Focused real-process CLI update, rollback and persistence checks.
|
|
125
|
+
npx vitest run electron/unitCli.test.ts
|
|
97
126
|
```
|
|
98
127
|
|
|
99
128
|
`node unit/verify-local.mjs --qbird /absolute/path/bluebird` 使用已构建的发行包,在临时目录验证安装、真实本地笔记、插件和引擎生命周期、重启持久化;不需要商业后端或数据库。`--serve` 可保留独立预览。必须使用与发行包原生模块匹配的 Node;构建时可用 `UNIT_SQLITE_PACKAGE` 指向同版本、目标 ABI 的 SQLite 包。
|
|
100
129
|
|
|
101
130
|
`node unit/verify-local.mjs --qbird /absolute/path/bluebird` verifies the built release in a temporary directory, including installation, real local notes, plugin and engine lifecycle, and restart persistence. It needs no commercial backend or database. `--serve` retains an isolated preview. Use a Node runtime matching the package's native modules; `UNIT_SQLITE_PACKAGE` can select the same locked SQLite version built for the target ABI.
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
## 管理 MCP 与 Unit 运维任务
|
|
134
|
+
|
|
135
|
+
Admin Panel MCP 新增 `unit_status`、`unit_releases`、`unit_operations`、`unit_operation_get`、`unit_plugin_action`、`unit_update`。
|
|
136
|
+
需同时更新 Unit 与 Server,并在实例私有 `unit.json` 顶层开启:
|
|
137
|
+
|
|
138
|
+
```json
|
|
139
|
+
{"management": {"enabled": true}}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
默认关闭。重启 Unit 后生效;该配置不下发浏览器。Unit 自己接管 `/api/admin/unit/*`,使用活动账户提供者重新验证原 Bearer、当前 ADMIN 账户与令牌权限,拒绝普通用户/伪造身份,并在提交与实际执行前再次验证。服务端校验不依赖模型传入的角色。
|
|
143
|
+
|
|
144
|
+
准备一次后,操作顺序为:
|
|
145
|
+
|
|
146
|
+
1. 用 owner MCP 令牌上传并提交 unit-release ZIP,或在部署机用 CLI 登记可信、已包含依赖的发行包:`node main.mjs stage /path/to/unit.json /path/to/bundled-package`。
|
|
147
|
+
2. 调用 `unit_releases` 选择 releaseId,`unit_status` 检查目标版本、状态与依赖。
|
|
148
|
+
3. 生成 UUID v4 requestId,调用 `unit_update`,提供 pluginId、releaseId、requestId、confirm:true。
|
|
149
|
+
4. 用同一 requestId 调用 `unit_operation_get`;连接中断时仍用该编号查询或重试,不另建编号。
|
|
150
|
+
|
|
151
|
+
stage 将包复制到 Unit 私有发行目录并保存 SHA256;安装前与安装副本都会检查摘要。源目录移动不影响已登记包。MCP 不接受包路径、下载 URL 或 shell 命令;npm-ci 包先在目标平台安装依赖并封装,远程任务不执行 npm 安装。发行目录最多保留 200 项,满后由本机运维归档不用的条目。
|
|
152
|
+
|
|
153
|
+
任务由 Unit 主进程持有,状态为 queued/running/succeeded/failed/interrupted,更新还显示 verifying-release/applying 阶段;保存操作人、目标、发行编号与时间;不持久化 Bearer、私有配置或完整包路径。最近 100 条任务持久化,幂等检查限于这些保留记录;同一编号换参数或换操作人会被拒绝。Unit 重启将未完成任务标为 interrupted,须先检查实际状态再决定是否重试。当前串行执行,一个任务运行时其他新任务返回 409。
|
|
154
|
+
|
|
155
|
+
`unit_plugin_action` 支持 enable/disable/restart/migrate。迁移须先停用目标模块;更新不自动迁移,失败尝试恢复旧代码,不回滚数据库。为保持远程恢复入口,停用或迁移账户提供者本身只能用本地 CLI;允许重启和更新账户提供者。Server 自身更新时其 MCP 连接可能断开,账户服务恢复前查询可能短暂失败,恢复后可继续查 Unit 保存的任务。
|
|
156
|
+
|
|
157
|
+
所有运维写操作都要求 confirm:true;它只是显式意图参数,真人审批仍由调用客户端负责。MCP auditor 可读取,operator 可启停/重启/更新已暂存包,owner 另可上传暂存包和迁移。账户提供者投射 ADMIN_SCOPED 与 adminPermissions;缺失权限时拒绝,账户解析须携带 administration 用途,旧 Unit 无法接收 scoped 身份,避免回滚后的越权。常规登录会话和旧未收窄令牌保留既有权限。
|
|
158
|
+
|
|
159
|
+
验收:`cd desktop && npx vitest run electron/unitManagement.test.ts electron/unitCli.test.ts electron/unitInstall.test.ts electron/unitRuntime.test.ts`。
|
|
160
|
+
真实 Server/MCP/Bluebird/私有 PG 验收见相邻 server 的 `scripts/verify-unit-installation.mjs --management --bluebird ...`。
|
|
161
|
+
|
|
162
|
+
上传、角色和本地直传 helper 详见 [Admin MCP](../../server/microserver/admin-mcp/README.md)。上传只登记发行包,激活仍须独立调用 unit_update。
|
package/backendWorker.mjs
CHANGED
|
@@ -192,7 +192,7 @@ function identityFields(value) {
|
|
|
192
192
|
if (value === null) return null;
|
|
193
193
|
if (!value || typeof value !== "object") throw new Error("Invalid account identity");
|
|
194
194
|
const identity = {};
|
|
195
|
-
for (const field of ["userId", "username", "role", "tenantId", "workspaceId", "nickname", "avatar"]) {
|
|
195
|
+
for (const field of ["userId", "username", "role", "tenantId", "workspaceId", "nickname", "avatar", "adminAccessRole"]) {
|
|
196
196
|
const input = value[field];
|
|
197
197
|
if (input === void 0 && !["userId", "username", "role"].includes(field)) continue;
|
|
198
198
|
const limit = field === "avatar" ? 1024 * 1024 : 512;
|
|
@@ -201,6 +201,10 @@ function identityFields(value) {
|
|
|
201
201
|
}
|
|
202
202
|
identity[field] = input;
|
|
203
203
|
}
|
|
204
|
+
if (value.adminPermissions !== void 0) {
|
|
205
|
+
if (!Array.isArray(value.adminPermissions) || value.adminPermissions.length > 32 || value.adminPermissions.some((v) => typeof v !== "string" || v.length > 64)) throw new Error("Invalid admin permissions");
|
|
206
|
+
identity.adminPermissions = [...value.adminPermissions];
|
|
207
|
+
}
|
|
204
208
|
return identity;
|
|
205
209
|
}
|
|
206
210
|
async function resolveAccount(command) {
|
|
@@ -211,7 +215,7 @@ async function resolveAccount(command) {
|
|
|
211
215
|
const call = new AbortController();
|
|
212
216
|
accountCalls.set(command.requestId, call);
|
|
213
217
|
try {
|
|
214
|
-
const result = await plugin.account.resolve(command.token, { signal: call.signal });
|
|
218
|
+
const result = await plugin.account.resolve(command.token, { signal: call.signal, purpose: command.purpose === "administration" ? "administration" : void 0 });
|
|
215
219
|
if (!call.signal.aborted && ready) send({ type: "account-result", requestId: command.requestId, identity: identityFields(result) });
|
|
216
220
|
} catch {
|
|
217
221
|
if (!call.signal.aborted && ready) send({ type: "account-error", requestId: command.requestId });
|